tools/utils/src/modules/string-[array-number].js

/**
* @module @svizzle/utils/string-[array-number]
*/

import * as _ from 'lamb';

/**
 * Return a function expecting an array of objects and returning the max of values by the provided key.
 * The same can be done by `arrayMaxWith(_.getKey(key))` but here we avoid invoking a function for all the items.
 * @see
 {@link module:@svizzle/utils/array-number.arrayMax|arrayMax},
 {@link module:@svizzle/utils/[any-number]-[array-number].arrayMaxWith|arrayMaxWith}
 *
 * @function
 * @arg {string} key
 * @return {function} - Array -> Number
 *
 * @example
> maxByA = arrayMaxBy('a')
> maxByA([{a: -1, b: -1}, {a: 0, b: 0}])
0
> maxByA([{a: 1, b: 1}, {a: 2, b: -2}])
2
 *
 * @since 0.1.0
 */
export const arrayMaxBy = key => _.reduceWith((max, item) => {
	const value = item[key];

	return value > max ? value : max;

	// no need to check if _.has(item, key) because:
	// undefined > -Infinity === false
}, -Infinity);


/**
 * Return a function expecting an array of objects and returning the min of values by the provided key
 * The same can be done by `arrayMinWith(_.getKey(key))` but here we avoid invoking a function for all the items.
 * @see
 {@link module:@svizzle/utils/array-number.arrayMin|arrayMin},
 {@link module:@svizzle/utils/[any-number]-[array-number].arrayMinWith|arrayMinWith}
 *
 * @function
 * @arg {string} key
 * @return {function} - Array -> Number
 *
 * @example
> minByA = arrayMinBy('a')
> minByA([{a: -1, b: -1}, {a: 0, b: 0}])
-1
> minByA([{a: 1, b: 1}, {a: 2, b: -2}])
1
 *
 * @since 0.1.0
 */
export const arrayMinBy = key => _.reduceWith((min, item) => {
	const value = item[key];

	return value < min ? value : min;

	// no need to check if _.has(item, key) because:
	// undefined < Infinity === false
}, Infinity);